using System;
using System.Collections;
using Evaluant.Uss;

namespace Evaluant.Uss.ObjectContext
{
    public class IdentityMap : IIdentityMap
    {
        private Hashtable innerDictionary = new Hashtable();

        /// <summary>
        /// Adds the specified object.
        /// </summary>
        /// <param name="persistable">The object to add.</param>
        /// <returns>False if the instance is already in the IndentityMap, true otherwise</returns>
        public bool Add(IPersistable persistable)
        {
            return Add(persistable.Entity.Id, persistable);
        }

        public bool Add(string key, object o)
        {
            if (innerDictionary.ContainsKey(key))
            {
                return false;
            }

            innerDictionary.Add(key, new WeakReference(o));
            return true;
        }

        public object Get(string key)
        {
            WeakReference wr;

            if (!innerDictionary.Contains(key))
            {
                return null;
            }
            else
            {
                wr = (WeakReference)innerDictionary[key];
            }

            object result = wr.Target;

            if (result == null)
            {
                innerDictionary.Remove(key);
                return null;
            }

            return result;
        }

        public void Clear()
        {
            innerDictionary.Clear();
        }

        public bool Remove(string key)
        {
            object p = Get(key);

            if (p == null)
                return false;

            if (p is IPersistable)
            {
                ((IPersistable)p).ObjectContext = null;
                innerDictionary.Remove(key);
            }

            return true;
        }

        private void CleanItems()
        {
            ArrayList deadKeys = new ArrayList();

            foreach (DictionaryEntry de in innerDictionary)
                if (((WeakReference)de.Value).Target == null)
                    deadKeys.Add(de.Key);

            foreach (object key in deadKeys)
                innerDictionary.Remove(key);
        }

    }
}